package com.coderfans.jedistest;

import com.coderfans.exception.SerializeException;
import com.coderfans.serialize.ISerialize;
import com.coderfans.serialize.JsonSerialize;
import com.google.common.collect.Lists;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.List;
import java.util.Set;

/**
 * Created by ${fanchunshuai} on 2016-10-12.
 *
 * @version: V1.0
 * @Desc:基于 redis 单机的数据缓存工具类
 * @Copyright (c) 2016 58到家-版权所有
 */
public class RedisCacheClient implements ISetRedisTest,IListRedisTest,IZSetRedisTest {

    private  JedisPool jedisPool = null;

    /**
     * 构造方法 传入JedisPool对象
     * @param jedisPool
     */
    public RedisCacheClient(JedisPool jedisPool){
        this.jedisPool = jedisPool;
    }

    private ISerialize serializer = new JsonSerialize();
    /**
     * 生成实际存储的key
     * @param namespace 命名空间 区分不同的键
     * @param key   bean的 id
     * @return
     */
    private byte[] generateKey(String namespace,String key ){
        if(key == null || "".equals(key)){
            return null;
        }
        return (namespace + key).getBytes();
    }


    /**
     * 将要存储的对象进行序列化
     * @param value
     * @return
     * @throws SerializeException
     */
    private byte[] generateValue(Object value) throws SerializeException {
        return serializer.serialize(value);
    }

    public <T> T disSerialize(byte [] data,Class<T> objectClass) throws SerializeException {
        return  (T)serializer.disSerialize(objectClass,data);
    }

    @Override
    public <T> long lpush(String field, String key, T... value) {
        Jedis jedis = jedisPool.getResource();
        try {
            return jedis.lpush(generateKey(field,key),generateValue(value));
        }  catch (SerializeException e) {
            e.printStackTrace();
        } finally {
            jedis.close();
        }
        return 0;
    }

    @Override
    public <T> long rpush(String field, String key, T... value) {
        return 0;
    }

    @Override
    public <T> long lpushx(String field, String key, T value) {
        Jedis jedis = jedisPool.getResource();
        try {
            System.out.println(generateValue(value).toString());
            return jedis.lpush(generateKey(field,key),generateValue(value));
        } catch (SerializeException e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
        return 0;
    }

    @Override
    public <T> long rpushx(String field, String key, T value) {
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.rpushx(generateKey(field,key),generateValue(value));
        } catch (SerializeException e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
        return 0;
    }

    @Override
    public <T> T lpop(String field, String key,Class<T> value) {
        Jedis jedis = jedisPool.getResource();
        try {
           return disSerialize(jedis.lpop(generateKey(field,key)),value);
        }  catch (SerializeException e) {
            e.printStackTrace();
        } finally {
            jedis.close();
        }
        return null;
    }

    @Override
    public <T> T blpop(String field, String key, int timeout,Class<T> value) {
        Jedis jedis = jedisPool.getResource();
        try {
            List<byte[]> list = jedis.blpop(timeout,generateKey(field,key));
            return  disSerialize(list.get(0),value);
        } catch (SerializeException e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
        return null;
    }

    @Override
    public <T> List<T> blpop(String field, String key,Class<T> value) {
        Jedis jedis = jedisPool.getResource();
        try {
           List<byte[]> bytes =  jedis.blpop(10000,generateKey(field,key));
            List<T> tList = Lists.newArrayList();
            for (byte [] bytes1: bytes){
                tList.add( disSerialize(bytes1,value));
            }
            return tList;
        } catch (SerializeException e) {
            e.printStackTrace();
        } finally {
            jedis.close();
        }
        return null;
    }

    @Override
    public <T> List<T> brpop(String field, String key) {
        return null;
    }

    @Override
    public <T> T brpop(String field, String key, int timeout) {
        return null;
    }

    @Override
    public <T> T rpop(String field, String key) {
        return null;
    }

    @Override
    public <T> T lindex(String field, String key, long index,Class<T> value) {
        Jedis jedis = jedisPool.getResource();
        try {
           return  disSerialize(jedis.lindex(generateKey(field,key),index),value);
        } catch (SerializeException e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
        return null;
    }

    @Override
    public long llen(String field, String key) {
        Jedis jedis = jedisPool.getResource();
        try {
           return jedis.llen(generateKey(field,key));
        }finally {
            jedis.close();
        }
    }

    @Override
    public <T> long lrem(String field, String key, long count, T value) {
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.lrem(generateKey(field,key),count,generateValue(value));
        } catch (SerializeException e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
        return 0;
    }

    @Override
    public <T> boolean lset(String field, String key, T value, long index) {
        return false;
    }

    @Override
    public boolean ltrim(String field, String key, long start, long stop) {
        return false;
    }

    @Override
    public <T> List<T> lrange(String field, String key, long start, long stop) {
        return null;
    }

    @Override
    public <T> long sadd(String field, String key, T value) {
        Jedis jedis = jedisPool.getResource();
        try {
            return jedis.sadd(generateKey(field,key),generateValue(value));
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
        return 0;
    }

    @Override
    public <T> T spop(String field, String key,Class<T> value) {
        Jedis jedis = jedisPool.getResource();
        try {
            return disSerialize(jedis.spop(generateKey(field, key)),value);
        } catch (SerializeException e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
        return null;
    }

    @Override
    public long scard(String field, String key) {
        Jedis jedis = jedisPool.getResource();
        try {
           return jedis.scard(generateKey(field, key));
        }finally {
            jedis.close();
        }
    }

    @Override
    public <T> long srem(String field, String key, T value) {
        Jedis jedis = jedisPool.getResource();
        try {
            return jedis.srem(generateKey(field,key),generateValue(value));
        } catch (SerializeException e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
        return 0;
    }

    @Override
    public <T> boolean sismember(String field, String key, T value) {
        Jedis jedis = jedisPool.getResource();
        try {
            return jedis.sismember(generateKey(field,key),generateValue(value));
        } catch (SerializeException e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
        return false;
    }

    @Override
    public void setSerializer(ISerialize serializer) {
        this.serializer = serializer;
    }

    @Override
    public Set smembers(String field, String key) {
        Jedis jedis = jedisPool.getResource();
        try {
            return jedis.smembers(generateKey(field,key));
        }finally {
            jedis.close();
        }
    }

    /**-----------------------redis zset 数据操作**/
    @Override
    public <T> long zadd(String field, String key,double score, T value) {
        Jedis jedis = jedisPool.getResource();
        try {
            return jedis.zadd(new String(generateKey(field,key)),score,new String(generateValue(value)));
        } catch (SerializeException e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
        return 0;
    }

    @Override
    public <T> long zrem(String field, String key,String... value) {
        Jedis jedis = jedisPool.getResource();
        try {
          return   jedis.zrem(field+key,value);
        }finally {
            jedis.close();
        }
    }

    @Override
    public Set zrange(String field, String key, long start, long stop, Class clazz) {
        return null;
    }

    @Override
    public long zcard(String field, String key) {
        Jedis jedis = jedisPool.getResource();
        try {
           return jedis.zcard(field+key);
        }finally {
            jedis.close();
        }
    }

    @Override
    public long zcount(String field, String key, double lowScore, double highScore) {
        Jedis jedis = jedisPool.getResource();

        try {
            return   jedis.zcount(field+key,lowScore,highScore);
        }finally {
            jedis.close();
        }
    }

    public void sayPing(){
        Jedis jedis = jedisPool.getResource();
        try {
            String pong = jedis.ping();
            System.out.println("> ping: "+pong);
        }finally {
            jedis.close();
        }
    }

}
